package com.leyou.item.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.common.pojo.PageResult;
import com.leyou.item.bo.SpuBo;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.mapper.StockMapper;
import com.leyou.item.pojo.*;
import com.leyou.item.service.BrandService;
import com.leyou.item.service.CategoryService;
import com.leyou.item.service.GoodsService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;


    private Logger logger = LoggerFactory.getLogger(GoodsServiceImpl.class);

    /**
     * 分页查询spu
     *
     * @param key
     * @param saleable
     * @param page
     * @param rows
     * @return
     */
    @Override
    public PageResult<SpuBo> querySpuByPage(String key, Boolean saleable, Integer page, Integer rows) {
        //开始分页
        PageHelper.startPage(page, rows);
        //根据条件动态的查询
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(key)) {
            criteria.andLike("title", "%" + key + "%");
        }
        //当判断为true的时候会与上面的语句拼接(saleable表示是否上架)
        if (null != saleable) {
            criteria.andEqualTo("saleable", saleable);
        }
        Page<Spu> spusPage = (Page<Spu>) spuMapper.selectByExample(example);
        //将查询到的spu转换为spuBo
        //用来存放spuBo
        List<SpuBo> spuBos = new ArrayList<>();
        List<Spu> spus = spusPage.getResult();
        spus.forEach(spu -> {
            SpuBo spuBo = new SpuBo();
            //深度拷贝将spu 的属性赋值给spuBo
            BeanUtils.copyProperties(spu, spuBo);
            List<String> names = this.categoryService.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
            //把查询到的分类的集合名称通过join转为字符串，赋值给cname
            spuBo.setCname(StringUtils.join(names, "/"));
            Brand brand = this.brandService.queryBrandById(spu.getBrandId());
            spuBo.setBname(brand.getName());
            spuBos.add(spuBo);
        });


        return new PageResult<>(spusPage.getTotal(), new Long(spusPage.getPages()), spuBos);
    }

    /**
     * 商品的新增保存
     *
     * @param spuBo
     */
    @Transactional
    @Override
    public void saveGoods(SpuBo spuBo) {
        //保存spu
        //下面的参数前台没有提交过来,需要后台进行补全
        spuBo.setSaleable(true);
        spuBo.setValid(true);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        this.spuMapper.insertSelective(spuBo);
        //保存spuDetail
        spuBo.getSpuDetail().setSpuId(spuBo.getId());
        this.spuDetailMapper.insertSelective(spuBo.getSpuDetail());
        //保存skus
        List<Sku> skus = spuBo.getSkus();
        //循环保存sku
        saveSku(spuBo, skus);
        //调用发消息的方法
        this.sendMessage(spuBo.getId(),"insert");

    }

    /**
     * 保存skus和stock和的通用方法
     *
     * @param spuBo
     * @param skus
     */
    private void saveSku(SpuBo spuBo, List<Sku> skus) {
        skus.forEach(sku -> {
            sku.setSpuId(spuBo.getId());
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            //保存sku,回显id
            this.skuMapper.insertSelective(sku);
            //保存库存
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            this.stockMapper.insertSelective(stock);
        });
    }

    /***
     * 商品修改数据的回显
     * @param id
     * @return
     */
    @Override
    public SpuDetail querySpuDetailById(Long id) {
        SpuDetail spuDetail = this.spuDetailMapper.selectByPrimaryKey(id);
        return spuDetail;
    }

    @Override
    public List<Sku> querySkuBySpuId(Long id) {
        //查询sku
        Sku record = new Sku();
        record.setSpuId(id);
        List<Sku> skus = this.skuMapper.select(record);
        //查询stock
        skus.forEach(sku ->
                sku.setStock(this.stockMapper.selectByPrimaryKey(sku.getId()).getStock())

        );
        return skus;
    }

    /**
     * 商品修改后的保存,和新增商品的逻辑是一样的
     *
     * @param spuBo
     */
    @Override
    @Transactional
    public void updateGoods(SpuBo spuBo) {
        System.out.println("spuBo = " + spuBo);
        //保存spu
        spuBo.setLastUpdateTime(new Date());
        this.spuMapper.updateByPrimaryKeySelective(spuBo);

        //这个方法为什么不行啊
        //this.spuMapper.insertSelective(spuBo);
        //保存spuDetail
        this.spuDetailMapper.updateByPrimaryKeySelective(spuBo.getSpuDetail());
        //保存sku(先查找出来删除(可以直接删除(但是需要写sql)),然后重新在添加)
        Sku record = new Sku();
        record.setSpuId(spuBo.getId());
        List<Sku> skus = this.skuMapper.select(record);
        skus.forEach(sku -> this.skuMapper.delete(sku));
        skus = null;
        //保存skus和stock
        saveSku(spuBo, spuBo.getSkus());
        //调用发消息的方法
        this.sendMessage(spuBo.getId(),"update");
    }

    @Override
    public Spu querySpuById(Long id) {
        Spu spu = this.spuMapper.selectByPrimaryKey(id);
        return spu;
    }

    /**
     * SpringAmqp 发送消息的方法，id就是spu的id，type就是增删改查
     * @param id
     * @param type
     */
    private void sendMessage(Long id, String type) {
        // 发送消息
        try {
            this.amqpTemplate.convertAndSend("item." + type, id);
        } catch (Exception e) {
            logger.error("{}商品消息发送异常，商品id：{}", type, id, e);
        }
    }
}


